iT邦幫忙

2023 iThome 鐵人賽

DAY 26
0
Software Development

Haskell 從入門到放棄系列 第 26

[Haskell 從入門到放棄] Day 26 - Monad (4)

  • 分享至 

  • xImage
  •  

Monad Law

畢竟 monad 是來自於數學上的概念,所以就算某個type 實作了 Monad 的 instance ,嚴格定義上我們也不能說它是 monad 。

就像 monoid law 或 functor law

Left identity

第一個規則是如果我們用 return 一個值 a 並把它用 >>= apply 到某個 function f 也就是 return a >>= f ,結果應該等於 f a

return 1 >>= (\x -> Just (x+1))  -- Just 2

(\x -> Just (x+1)) 1  -- Just 2

return 'a' >>= (\x -> [x,x,x])  --- "aaa"

(\x -> [x,x,x]) 'a'  --- "aaa"

return 的 type 的是 Monad m => a -> m a ,那 return 1 就變成一個是 monadic value 然後 >>= 的 type 是 Monad m => m a -> (a -> m b) -> m b ,所以 return 1 變成 m a 然後 (\x -> Just (x+1)) 就是 (a → m b) 所以最後將 return 1 丟進去 (\x -> Just (x+1)) 就會是 Just 2

那反過來說就相當簡單 (\x -> Just (x+1)) 1 ,就是很簡單的 (a → m b) 傳入一個 a 最後回傳 m b

簡單來說就是 >>= 將左邊的運算元的 monadic value 的 context 打開後餵進去右邊的 function 。那本來右邊的 function 就是將一個 value 變成 monadic value 的 function 。所以我直接將這個「 function apply 給那個 value 」跟「將同樣的值但是是包裝在 context 用 >>= 丟進同樣的function 」的結果會是一樣的。

Right identity

第二個規則就是如果我們將 monadic value a>>= apply 給 return 那結果應該是 a

Just 1 >>= (\x -> return x)  -- Just 1

"aaa" >>= (\x -> return x)  -- "aaa"

如上面所提到的 >>= 簡單來說就是將 monadic value 把它從 context 中的值給 apply 到一個function 但最後維持一樣的 context 。return 則是將一個 value 轉換成 monadic value。

那所以我將一個 monadic value 的值從 context 中取出來並再包裝一次 context 當然會是一樣的 monadic value 。

Associativity

第三個規則是如果我們用 >>= 串接不同的 function 不管誰先執行結果都應該一樣。

(Just 2 >>= (\x -> Just(x*2))) >>= (\x -> Just(x*3)) -- Just 12

Just 2 >>= (\x -> Just(x*2) >>= (\x -> Just(x*3))) -- Just 12

(Just 2 >>= (\x -> Just(x+3))) >>= (\x -> Just(x*3)) -- Just 15

Just 2 >>= (\x -> Just(x+3) >>= (\x -> Just(x*3))) -- Just 15

這邊看的出來不管我們是先執行 (Just 2 >>= (\x -> Just(x*2))) 然後再 >>= (\x -> Just(x*3) 或者是先讓 (\x -> Just(x*2) >>= (\x -> Just(x*3))) 後再用 >>=Just 2 傳進去,結果都會是一樣的。

跟一般的 function composition . 一樣,對於 monadic function 也是有 composition 的語法 <=<


:t (<=<) -- (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
((\x -> Just(x*3)) <=< (\x -> Just(x+3))) 2  -- Just 12

<=< 的定義也跟 . 很像,從 f . g = (\x -> f (g x)) 變成了 f <=< g = (\x -> g x >>= f)


上一篇
[Haskell 從入門到放棄] Day 25 - Monad (3)
下一篇
[Haskell 從入門到放棄] Day 27 - newtype
系列文
Haskell 從入門到放棄30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言